/*
 * $Id$
 *
 * Copyright ( c ) 2014 XuNuo Corporation. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of XuNuo
 * Corporation ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with the terms
 * of the license agreement you entered into with XuNuo Corporation or a XuNuo
 * authorized reseller (the "License Agreement"). XuNuo may make changes to the
 * Confidential Information from time to time. Such Confidential Information may
 * contain errors.
 *
 * EXCEPT AS EXPLICITLY SET FORTH IN THE LICENSE AGREEMENT, XuNuo DISCLAIMS ALL
 * WARRANTIES, COVENANTS, REPRESENTATIONS, INDEMNITIES, AND GUARANTEES WITH
 * RESPECT TO SOFTWARE AND DOCUMENTATION, WHETHER EXPRESS OR IMPLIED, WRITTEN OR
 * ORAL, STATUTORY OR OTHERWISE INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A
 * PARTICULAR PURPOSE. XuNuo DOES NOT WARRANT THAT END USER'S USE OF THE
 * SOFTWARE WILL BE UNINTERRUPTED, ERROR FREE OR SECURE.
 *
 * XuNuo SHALL NOT BE LIABLE TO END USER, OR ANY OTHER PERSON, CORPORATION OR
 * ENTITY FOR INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL
 * DAMAGES, OR DAMAGES FOR LOSS OF PROFITS, REVENUE, DATA OR USE, WHETHER IN AN
 * ACTION IN CONTRACT, TORT OR OTHERWISE, EVEN IF XuNuo HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES. XuNuo' TOTAL LIABILITY TO END USER SHALL NOT
 * EXCEED THE AMOUNTS PAID FOR THE XuNuo SOFTWARE BY END USER DURING THE PRIOR
 * TWELVE (12) MONTHS FROM THE DATE IN WHICH THE CLAIM AROSE.  BECAUSE SOME
 * STATES OR JURISDICTIONS DO NOT ALLOW LIMITATION OR EXCLUSION OF CONSEQUENTIAL
 * OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO END USER.
 *
 * Copyright version 2.0
 */
package com.th.supcom.pds.common.client.widget;

import java.util.ArrayList;
import java.util.List;

import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.store.GroupingStore;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.grid.AggregationRenderer;
import com.extjs.gxt.ui.client.widget.grid.AggregationRowConfig;
import com.extjs.gxt.ui.client.widget.grid.CheckColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.grid.GridGroupRenderer;
import com.extjs.gxt.ui.client.widget.grid.GroupColumnData;
import com.extjs.gxt.ui.client.widget.grid.GroupingView;
import com.extjs.gxt.ui.client.widget.grid.RowNumberer;
import com.extjs.gxt.ui.client.widget.grid.SummaryType;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.th.supcom.pds.common.client.commom.SimpleMethod;
import com.th.supcom.pds.common.utils.ClientUtils;

/**
 * 处方明细表格工具类，对收方收费、核对发药、后台拣药的公共部分进行提取<br/>
 * 现有数据列{序号，药品编码，药品名称，药品规格，包装单位,数量，价格，金额，服法}<br/>
 * 对应的Issue号：EARTH-2287<br/>
 * 不显示静配复选框，不对列配置进行补充Example:
 * <p>
 * 
 * <pre>
 * PrescDetailGrid &lt;PdsPrescDetailInfoModel&gt; grid = new PrescDetailGrid &lt;PdsPrescDetailInfoModel&gt; ();
 * layoutContainer.add (grid);
 * </pre>
 * 
 * </p>
 * 显示静配复选框：Example:
 * <p>
 * 
 * <pre>
 * PrescDetailGrid &lt;PdsPrescDetailInfoModel&gt; grid = new PrescDetailGrid &lt;PdsPrescDetailInfoModel&gt; (Boolean.TRUE);
 * layoutContainer.add (grid);
 * </pre>
 * 
 * </p>
 * 对列数据进行补充{追加新的列}Example:
 * <p>
 * 
 * <pre>
 * PrescDetailGrid &lt;PdsPrescDetailInfoModel&gt; grid = new PrescDetailGrid &lt;PdsPrescDetailInfoModel&gt; (new ColumnConfigEnhance ()
 * {
 *     &#064;Override
 *     public void enhance (List &lt;ColumnConfig&gt; configs)
 *     {
 *         ColumnConfig column = new ColumnConfig ();
 *         column.setId (&quot;phameName&quot;);
 *         column.setHeader (&quot;药品名称&quot;);
 *         column.setWidth (80);
 *         configs.add (column);
 *     }
 * });
 * layoutContainer.add (grid);
 * 
 * <pre>
 * </p>
 * 
 * @author wangweiquan
 */
public class PrescDetailGrid <T extends ModelData> extends ContentPanel
{
    private Grid <T> m_grid;
    /**
     * 是否在院输液
     */
    private final Boolean m_isInfusion;

    /** 公司版权信息. */
    public static final String copyright = "Copyright 2014, TH Supcom Corporation";
    private static final String MONEY_KEY = "costs";
    /** 提交路径. */
    public static final String SCC_BRANCH = "$URL$";

    /** 提交日期. */
    public static final String SCC_LAST_MODIFICATION_DATE = "$Date$";

    /** 最终修改人员. */
    public static final String SCC_LAST_MODIFIER_NAME = "$Author$";

    /** 最终版本号. */
    public static final String SCC_REVISION = "$Revision$";

    private final ColumnConfigEnhance m_columnConfigEnhance;

    /**
     * 处方明细表格列数据加强接口
     * 
     * @author wangweiquan
     */
    public static interface ColumnConfigEnhance
    {
        /**
         * 列数据加强
         * 
         * @param configs 可进行操作的列配置集合
         */
        public void enhance (List <ColumnConfig> configs);
    }

    /**
     * 默认不在院输液
     */
    public PrescDetailGrid ()
    {
        this (false);
    }

    /**
     * @param isInfusion 是否在院输液
     */
    public PrescDetailGrid (final Boolean isInfusion)
    {
        this (isInfusion, null);
    }

    /**
     * @param isInfusion 是否在院输液
     */
    public PrescDetailGrid (final Boolean isInfusion, final ColumnConfigEnhance enhance)
    {
        this.m_isInfusion = null == isInfusion ? Boolean.FALSE : isInfusion;
        this.m_columnConfigEnhance = enhance;
        initUI ();
    }

    /**
     * @param isInfusion 是否在院输液
     */
    public PrescDetailGrid (final ColumnConfigEnhance enhance)
    {
        this (false, enhance);
    }

    /**
     * 清除处方明细表格中的所有数据
     */
    public final void clear ()
    {
        m_grid.getStore ().removeAll ();
    }

    private AggregationRowConfig <T> createAggregationRowConfig ()
    {
        final AggregationRowConfig <T> config = new AggregationRowConfig <T> ();
        config.setHtml ("unitNameName", "合计");
        config.setSummaryType (PrescDetailGrid.MONEY_KEY, SummaryType.SUM);
        config.setRenderer (PrescDetailGrid.MONEY_KEY, new AggregationRenderer <T> ()
        {
            @Override
            public Object render (final Number value, final int colIndex, final Grid <T> grid, final ListStore <T> store)
            {
                String displayValue = "0.00";
                if (null != value)
                {
                    displayValue = ClientUtils.formatNumTwo ((Double) value);
                }
                return "<span style='color:red;font-weight:bold;'>" + displayValue + "</span>";
            }
        });
        return config;
    }

    /**
     * 
     * @param id 显示的列内容数据来源Key
     * @param header 列标题
     * @param width 列宽
     * @param alignment 对齐方式
     * @return
     */
    private final ColumnConfig createColumnConfig (final String id, final String header, final int width, final HorizontalAlignment alignment, final boolean isDigit)
    {
        final ColumnConfig column = new ColumnConfig ();
        column.setId (id);
        column.setHeader (header);
        column.setWidth (width);
        column.setAlignment (alignment);
        if (isDigit)
        {
            column.setRenderer (ClientUtils.getRenderer (id));
        }
        return column;
    }

    private final ColumnModel createColumnModel ()
    {
        final List <ColumnConfig> columns = new ArrayList <ColumnConfig> ();
        if (m_isInfusion)
        {
            columns.add (new CheckColumnConfig ("infusion", "是否静配", 80));
        }
        final RowNumberer rowNumber = new RowNumberer ();
        rowNumber.setHeader ("序号");
        rowNumber.setWidth (40);
        rowNumber.setRenderer (ClientUtils.createRowNumberRenderer ("prescNo"));
        columns.add (rowNumber);
        columns.add (createColumnConfig ("phamName", "药品名称", 130, HorizontalAlignment.LEFT, false));
        columns.add (createColumnConfig ("phamSpec", "药品规格", 130, HorizontalAlignment.LEFT, false));
        columns.add (createColumnConfig ("unitQty", "包装数量", 50, HorizontalAlignment.LEFT, true));
        columns.add (createColumnConfig ("packageUnitName", "包装单位", 50, HorizontalAlignment.LEFT, false));
        columns.add (createColumnConfig ("qtySum", "数量", 50, HorizontalAlignment.LEFT, true));
        columns.add (createColumnConfig ("qtyUnitName", "单位", 50, HorizontalAlignment.LEFT, false));
        final ColumnConfig config = createColumnConfig (PrescDetailGrid.MONEY_KEY, "金额", 80, HorizontalAlignment.LEFT, false);
        config.setRenderer (createPriceRenderer ());
        columns.add (config);
        final ColumnConfig config1=createColumnConfig ("freqTimeQty", "服法", 80, HorizontalAlignment.LEFT, false);
        config1.setRenderer (ClientUtils.createUsageRenderer ());
        columns.add (config1);
        columns.add (createColumnConfig ("allocation", "货位", 80, HorizontalAlignment.LEFT, false));
        if (null != m_columnConfigEnhance)
        {
            m_columnConfigEnhance.enhance (columns);
        }
        return new ColumnModel (columns);
    }

    private GroupingView createGroupingView ()
    {
        final GroupingView view = new GroupingView ();
        view.setShowGroupedColumn (false);
        view.setForceFit(true);
        view.setEmptyText ("暂时没有您需要的数据...");
        view.setGroupRenderer (new GridGroupRenderer ()
        {
            @Override
            public String render (final GroupColumnData data)
            {
                
                final String prescNo = data.models.get (0).get ("prescNo");
                List<ModelData>list=data.models;
                Double prescPrice=0.0;
                for (ModelData modelData : list)
                {
                    prescPrice=+(Double)modelData.get ("costs");
                }
                if(prescNo==null){
                   return "其他"; 
                }
                return "处方号: " + prescNo +" 金额: " + ClientUtils.formatNumTwo (prescPrice) +" (" + data.models.size () + " 条明细)";
            }
        });
        return view;
    }

    private GridCellRenderer <ModelData> createPriceRenderer ()
    {
        return new GridCellRenderer <ModelData> ()
        {

            @Override
            public Object render (final ModelData model, final String property, final ColumnData config, final int rowIndex, final int colIndex, final ListStore <ModelData> store,
                                  final Grid <ModelData> grid)
            {

                final Double costs = model.get ("costs");
                Double price = 0D;
                if (null != costs)
                {
                    price = costs;
                }
                model.set (PrescDetailGrid.MONEY_KEY, SimpleMethod.retainDoubleTwo (price));
                return "<span style='float:right'>" + ClientUtils.formatNumTwo ((Double) model.get (PrescDetailGrid.MONEY_KEY)) + "</span>";
            }
        };
    }

    private GroupingStore <T> createStore ()
    {
        final GroupingStore <T> store = new GroupingStore <T> ();
        store.groupBy ("prescNo");
        return store;
    }

    /**
     * 获得表格中的所有处方明细数据
     * 
     * @return
     */
    public final List <T> getDetailData ()
    {
        return m_grid.getStore ().getModels ();
    }

    /**
     * 获得被包装的Grid对象，慎用
     * 
     * @return
     */
    public Grid <T> getGrid ()
    {

        return m_grid;
    }

    private void initGrid ()
    {
        final ColumnModel columnModel = createColumnModel ();
        columnModel.addAggregationRow (createAggregationRowConfig ());
        m_grid = new EditorGrid <T> (createStore (), columnModel);
        m_grid.setView (createGroupingView ());
        m_grid.setStripeRows (true);
        m_grid.setColumnLines (true);
        m_grid.setMinColumnWidth (10);
    }

    private void initUI ()
    {
        this.setLayout (new FitLayout ());
        setHeaderVisible (false);
        initGrid ();
        this.add (m_grid);
    }

    /**
     * 刷新处方明细表格
     * 
     * @param detail 新增到表格中的数据
     */
    public final void refresh (final List <T> detail)
    {
        this.clear ();
        if (null != detail && !detail.isEmpty ())
        {
            m_grid.getStore ().add (new ArrayList <T> (detail));
        }
    }
}
